package cn.ghx.xboot.douyin;

import cn.ghx.xboot.client.Client;
import cn.ghx.xboot.client.ClientService;
import cn.ghx.xboot.douyin.dto.Code2SessionResult;
import cn.ghx.xboot.douyin.dto.DouyinResult;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@Service
public class DouyinService {

    public static final String BASE_URL = "https://developer.toutiao.com";

    private static String APP_PRIVATE_KEY = "";
    private final DouyinParam param;
    private final ClientService clientService;

    @Resource
    private ResourceLoader resourceLoader;

    @Lazy
    public DouyinService(DouyinParam param, ClientService clientService) {
        this.param = param;
        this.clientService = clientService;
    }

    @PostConstruct
    public void init() {
        // 读取 public_key.pem 赋值给 PUBLIC_KEY
        try {
            APP_PRIVATE_KEY = resourceLoader.getResource("classpath:app_private_key.pem").getContentAsString(StandardCharsets.UTF_8);
        } catch (IOException e) {
            log.error("读取public-key.pem失败:{}", e.getLocalizedMessage());
        }
    }

    public Client code2SessionClient(String code, String anonymousCode) throws Exception {

        Code2SessionResult rs =  getCode2Session(code,anonymousCode);

        return clientService.saveOrUpdateBySession(rs);
    }

    private Code2SessionResult getCode2Session(String code, String anonymousCode) throws Exception {
        String path = "/api/apps/v2/jscode2session";
        Map<String, Object> params = new HashMap<>() {{
            if (StringUtils.hasText(code)) {
                put("code", code);
            }
            if (StringUtils.hasText(anonymousCode)) {
                put("anonymous_code", anonymousCode);
            }
        }};
        DouyinResult<Code2SessionResult> resp = request("POST", path, params, Code2SessionResult.class);
        return resp.getData();
    }

    private <T> DouyinResult<T> request(String method, String path, Map<String, Object> params, Class<T> clazz) throws Exception {

        params.put("appid", param.getAppId());
        params.put("secret", param.getAppSecret());

        long timestamp = System.currentTimeMillis() / 1000;
        String nonce = RandomUtil.randomString(4);
        String body = JSONUtil.toJsonStr(params);
        String sign = SignTool.getSignature(
                APP_PRIVATE_KEY,
                method,
                path,
                timestamp,
                nonce,
                body
        );
        String auth = "SHA256-RSA2048 appid=\"" + param.getAppId() + "\",nonce_str=\"" + nonce + "\",timestamp=\"" + timestamp + "\",key_version=\"1\",signature=\"" + sign + "\"";
        try (HttpResponse resp = HttpRequest.post(BASE_URL + path)
                .body(body)
                .header("Byte-Authorization", auth)
                .timeout(20000)//超时，毫秒;
                .execute()) {

            String respBody = resp.body();
            log.debug(respBody);

            JSONObject respObj = JSONUtil.parseObj(respBody);

            DouyinResult<T> rs = new DouyinResult<>();
            rs.setErrNo(respObj.getInt("err_no"));
            rs.setErrTips(respObj.getStr("err_tips"));
            rs.setData(respObj.get("data", clazz));
            return rs;
        }
    }

}
